package gov.dhs.cis.soa.readers;

import gov.dhs.cis.soa.SOAData;
import gov.dhs.cis.soa.Utils;
import gov.dhs.cis.soa.Constants.DataDirType;
import gov.dhs.cis.soa.data.EntitiesReferences;
import gov.dhs.cis.soa.data.Interface;
import gov.dhs.cis.soa.data.Processes;
import gov.dhs.cis.soa.data.RelatedDataReference;
import gov.dhs.cis.soa.data.Service;

import java.util.List;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;


public class Process2EntitiesRefReader extends ExcelReader {
	static final Logger loger = Logger.getLogger(Process2EntitiesRefReader.class);

	private final String PROC_SERV_FILE_NAME = "USCIS Architecture Components - Processes to Services and Data.xls";
	String SHEET_NAME = "Processes";
	
	private String REL_COL_NUM = "C";
	private String PROC_COL_NUM = "D";
	private String TYPE_COL_NUM = "F";
	private String ENT_COL_NUM = "G";
	private String DATA_IN_COL_NUM = "H";
	private String DATA_OUT_COL_NUM = "I";
	
	private int MAX_PROCS = 925;

	private SOAData soaData = null;
	
	public SOAData extractProcess2Entities(SOAData sData) {
		loger.debug("Extracting Process-Services layer Sheet...");
		soaData = sData;
		associate2Processes();
		return soaData;
	}

	private SOAData associate2Processes() {
		HSSFWorkbook w = openFile(PROC_SERV_FILE_NAME);
		HSSFSheet s1 = w.getSheet(SHEET_NAME);
		int rows = s1.getLastRowNum();
		loger.debug("S1 rows =" + rows);
		
		for (int n = 2; n < MAX_PROCS; n++) {
			HSSFRow row = s1.getRow(n);
			if(row == null)
				continue;
			String rel = getCellStringValue(w, row, REL_COL_NUM);
			if(Utils.isEmpty(rel) || "DEL".equalsIgnoreCase(rel)) {
				loger.warn("Process has empty release or marked for delete proc_services file for row# : " + n + ", skipping.");
				continue;
			}
			String procName = getCellStringValue(w, row, PROC_COL_NUM);
			if(Utils.isEmpty(procName))
				continue;
			String type = getCellStringValue(w, row, TYPE_COL_NUM);
			if(Utils.isEmpty(type) || "D".equalsIgnoreCase(type))
				continue;
			String entityName = getCellStringValue(w, row, ENT_COL_NUM);
			if(Utils.isEmpty(entityName)) {
				loger.debug("Entity name in proc_services file is empty for row# : " + n);
				continue;
			}
			Processes proc = Utils.findProcessByName(procName, soaData.procList);
			if(proc == null) {
				loger.error(n + " :: Process name can't be found in Processes table for : [" + procName + "]");
				continue;
			}
			String dataIn = getCellStringValue(w, row, DATA_IN_COL_NUM);
			String dataOut = getCellStringValue(w, row, DATA_OUT_COL_NUM);

			if("S".equalsIgnoreCase(type)) {
				Service serv = Utils.findServiceByName(entityName, soaData.servList);
				if(serv == null) {
					loger.error(n + " :: Services name can't be found in Services table for : [" + entityName + "] - [" + procName + "]");
					continue;
				}
				/*
				 * Data In and Data Out are done by accumulating from service operations in SOAData class in the end - RSingh 04/01/2010
				 * 
				List<RelatedDataReference> inList = Utils.createNewRefDataClasses(soaData, dataIn, DataDirType.I, EntityType.SERV, serv.id, serv.name);
				List<RelatedDataReference> outList = Utils.createNewRefDataClasses(soaData, dataOut, DataDirType.O, EntityType.SERV, serv.id, serv.name);
				soaData.addRelatedDataReference(inList);
				soaData.addRelatedDataReference(outList);
				//proc.addReferedSerivice(serv, soaData);
				*/
				soaData.addEntitiesReferences(EntitiesReferences.getNewEntitiesReference(proc, serv, null));
			} else {
				Interface interBO = Utils.findInterfaceByName(entityName, soaData.intList);
				if(interBO == null) {
					loger.error(n + " :: Interface name can't be found in Interfaces table for : [" + entityName + "] - [" + procName + "]");
					continue;
				}
				List<RelatedDataReference> inList = Utils.createNewRefDataClasses(soaData, dataIn, DataDirType.I, interBO);
				List<RelatedDataReference> outList = Utils.createNewRefDataClasses(soaData, dataOut, DataDirType.O, interBO);
				soaData.addRelatedDataReference(inList);
				soaData.addRelatedDataReference(outList);
				//proc.addReferedInterface(interBO);
				//soaData.addEntitiesReferences(EntitiesReferences.getNewEntitiesReference(proc.id, EntityType.PROC, interBO.id, EntityType.INTR, null));
				soaData.addEntitiesReferences(EntitiesReferences.getNewEntitiesReference(interBO, proc, null));
			}
		}
		closeAll(w);
		return soaData;
	}
}
